package com.hll.api.util;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;

/**
 * 安全工具类，包含授权签名所需的hmac_sha1算法，主要用于计算签名
 * @author 何龙
 */
public final class SecurityUtil {

	public static final String HMAC_SHA1 = "HmacSHA1";

	/**
	 * HMAC see：http://www.ietf.org/rfc/rfc2104.txt
	 */
	public static byte[] hmacSha1(byte[] data, byte[] key, int offset, int len) {
		SecretKeySpec signingKey = new SecretKeySpec(key, HMAC_SHA1);
		Mac mac;
		try {
			mac = Mac.getInstance(HMAC_SHA1);
			mac.init(signingKey);
		} catch (NoSuchAlgorithmException | InvalidKeyException e) {
			throw new RuntimeException(e.getMessage(), e);
		}
		mac.update(data, offset, len);
		return mac.doFinal();
	}

	public static byte[] hmacSha1(byte[][] datas, byte[] key) {
		SecretKeySpec signingKey = new SecretKeySpec(key, HMAC_SHA1);
		Mac mac;
		try {
			mac = Mac.getInstance(HMAC_SHA1);
			mac.init(signingKey);
		} catch (NoSuchAlgorithmException | InvalidKeyException e) {
			throw new RuntimeException(e.getMessage(), e);
		}
		for (byte[] data : datas) {
			mac.update(data);
		}
		return mac.doFinal();
	}

	public static byte[] hmacSha1(String[] datas, byte[] key) {
		SecretKeySpec signingKey = new SecretKeySpec(key, HMAC_SHA1);
		Mac mac;
		try {
			mac = Mac.getInstance(HMAC_SHA1);
			mac.init(signingKey);
		} catch (NoSuchAlgorithmException | InvalidKeyException e) {
			throw new RuntimeException(e.getMessage(), e);
		}
		for (String data : datas) {
			mac.update(data.getBytes(StandardCharsets.UTF_8));
		}
		return mac.doFinal();
	}

	public static String hmacSha1ToHexStr(byte[] data, byte[] key, int offset, int len) {
		byte[] rawHmac = hmacSha1(data, key, offset, len);
		return StringUtil.encodeHexStr(rawHmac);
	}

	public static String hmacSha1ToHexStr(byte[] data, String key, int offset, int len) {
		return hmacSha1ToHexStr(data, key.getBytes(StandardCharsets.UTF_8), offset, len);
	}

	public static String hmacSha1ToHexStr(String str, String key) {
		byte[] data = str.getBytes(StandardCharsets.UTF_8);
		return hmacSha1ToHexStr(data, key.getBytes(StandardCharsets.UTF_8), 0, data.length);
	}

	private SecurityUtil() {
	}
}
